﻿using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UMLSynthesizer.CSharpAnalyzer.Statements;
using UMLSynthesizer.LangAnalyzer.Statements;

namespace UMLSynthesizer.CSharpAnalyzer.Helpers
{
    class CSharpStatementBlockHelper
    {
        #region Fields

        IBlockStatementBase blockStatement;
        IEnumerable<IStatementBase> _containedStatements;

        #endregion

        #region Delegates

        Func<IEnumerable<StatementSyntax>> GetStatementNodes;

        #endregion

        #region Constructor

        public CSharpStatementBlockHelper(IBlockStatementBase blockStatement,
            Func<IEnumerable<StatementSyntax>> getStatementNodes)
        {
            this.blockStatement = blockStatement;
            this.GetStatementNodes = getStatementNodes;
        }

        #endregion

        #region Properties

        public IEnumerable<IStatementBase> ContainedStatements
        {
            get
            {
                if (GetStatementNodes == null)
                    throw new InvalidOperationException("You can't get ContainedStatements if the GetStatementNodes delegate is null");

                if (_containedStatements == null)
                {
                    List<IStatementBase> statementList = new List<IStatementBase>();
                    foreach (var statement in GetStatementNodes())
                    {
                        var csharpStatement = CreateCSharpStatement(statement);
                        if (csharpStatement != null)
                            statementList.Add(csharpStatement);
                    }
                    _containedStatements = statementList;
                }

                return _containedStatements;
            }
        }

        #endregion

        #region Public interface

        public IStatementBase CreateCSharpStatement(StatementSyntax statement)
        {
            switch (statement.CSharpKind())
            {
                case SyntaxKind.BreakStatement:
                    return new CSharpBreakStatement(statement as BreakStatementSyntax, blockStatement);
                case SyntaxKind.Block:
                    return new CSharpBlockStatement(statement as BlockSyntax, blockStatement);
                case SyntaxKind.CheckedStatement:
                    break;
                case SyntaxKind.ContinueStatement:
                    return new CSharpContinueStatement(statement as ContinueStatementSyntax, blockStatement);
                case SyntaxKind.DoStatement:
                    return new CSharpDoStatement(statement as DoStatementSyntax, blockStatement);
                case SyntaxKind.EmptyStatement:
                    break;
                case SyntaxKind.ExpressionStatement:
                    return new CSharpExpressionStatement(statement as ExpressionStatementSyntax, blockStatement);
                case SyntaxKind.FixedStatement:
                    break;
                case SyntaxKind.ForEachStatement:
                    return new CSharpForeachStatement(statement as ForEachStatementSyntax, blockStatement);
                case SyntaxKind.ForStatement:
                    return new CSharpForStatement(statement as ForStatementSyntax, blockStatement);
                case SyntaxKind.GlobalStatement:
                    break;
                case SyntaxKind.GotoCaseStatement:
                    break;
                case SyntaxKind.GotoDefaultStatement:
                    break;
                case SyntaxKind.GotoStatement:
                    return new CSharpGotoStatement(statement as GotoStatementSyntax, blockStatement);
                case SyntaxKind.IfStatement:
                    return new CSharpIfStatement(statement as IfStatementSyntax, blockStatement);
                case SyntaxKind.LabeledStatement:
                    return new CSharpLabeledStatement(statement as LabeledStatementSyntax, blockStatement);
                case SyntaxKind.LocalDeclarationStatement:
                    return new CSharpLocalDeclarationStatement(statement as LocalDeclarationStatementSyntax, blockStatement);
                case SyntaxKind.LockStatement:
                    return new CSharpLockStatement(statement as LockStatementSyntax, blockStatement);
                case SyntaxKind.ReturnStatement:
                    return new CSharpReturnStatement(statement as ReturnStatementSyntax, blockStatement);
                case SyntaxKind.SwitchStatement:
                    return new CSharpSwitchStatement(statement as SwitchStatementSyntax, blockStatement);
                case SyntaxKind.ThrowStatement:
                    return new CSharpThrowStatement(statement as ThrowStatementSyntax, blockStatement);
                case SyntaxKind.TryStatement:
                    return new CSharpTryStatement(statement as TryStatementSyntax, blockStatement);
                case SyntaxKind.UncheckedStatement:
                    break;
                case SyntaxKind.UnsafeStatement:
                    break;
                case SyntaxKind.UsingStatement:
                    break;
                case SyntaxKind.WhileStatement:
                    return new CSharpWhileStatement(statement as WhileStatementSyntax, blockStatement);
                case SyntaxKind.YieldBreakStatement:
                    break;
                case SyntaxKind.YieldReturnStatement:
                    break;
            }
            return null;
        }

        #endregion
    }
}
